package org.jflame.context.security.mask;

import org.jflame.commons.util.StringHelper;
import org.jflame.context.security.SecurityFacade;
import org.jflame.context.security.mask.MaskRule.NoneMaskFunc;
import org.jflame.context.security.mask.jackson.JacksonMask;

import java.lang.reflect.InvocationTargetException;
import java.util.function.Function;

public class MaskHandler implements Function<String,String> {

    private Function<String,String> converter;
    private String dataId = null;

    public MaskHandler(Function<String,String> converter, String dataId) {
        this.converter = converter;
        if (StringHelper.isNotEmpty(dataId)) {
            this.dataId = dataId;
        }
    }

    @Override
    public String apply(String t) {
        if (StringHelper.isEmpty(t)) {
            return t;
        }
        if (dataId != null && !SecurityFacade.requireMask(dataId)) {
            return t;
        }

        return converter.apply(t);
    }

    public static MaskHandler build(Mask maskAnnot) {
        Function<String,String> converter;
        if (maskAnnot.rule() != MaskRule.NONE) {
            converter = maskAnnot.rule()
                    .getMaskFun();
        } else if (maskAnnot.ruleClass() != NoneMaskFunc.class) {
            try {
                converter = maskAnnot.ruleClass()
                        .getDeclaredConstructor()
                        .newInstance();
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                throw new InstantiationError(e.getMessage());
            }
        } else {
            final int head = maskAnnot.head();
            final int tail = maskAnnot.tail();
            final int symbolSize = maskAnnot.symbolSize();
            converter = (s) -> StringHelper.masked(s, head, tail, '*', symbolSize);
        }
        return new MaskHandler(converter, maskAnnot.dataId());
    }

    public static MaskHandler build(JacksonMask maskAnnot) {
        Function<String,String> converter;
        if (maskAnnot.rule() != MaskRule.NONE) {
            converter = maskAnnot.rule()
                    .getMaskFun();
        } else if (maskAnnot.ruleClass() != NoneMaskFunc.class) {
            try {
                converter = maskAnnot.ruleClass()
                        .getDeclaredConstructor()
                        .newInstance();
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                throw new InstantiationError("无法实例化" + maskAnnot.ruleClass()
                        .getName() + ", 原因:" + e.getMessage());
            }
        } else {
            final int head = maskAnnot.head();
            final int tail = maskAnnot.tail();
            final int symbolSize = maskAnnot.symbolSize();
            converter = (s) -> StringHelper.masked(s, head, tail, '*', symbolSize);
        }
        return new MaskHandler(converter, maskAnnot.dataId());
    }
}
